package gameElements;
import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;

/**
 * GController.java
 * 
 * Fredrik Wallenius and Peter Steiner 
 * DP08 - KTH - 2009
 *
 */
public class GController extends GBox{

	private double tmpX;
	private Point p = new Point();
	private boolean moveLeft = false, moveRight = false;
	private int size = 0;
	private int oneStepMovement = 30;
	private double surfaceHight = 10;
	private boolean increaseBallSpeed;
	private boolean decreaseBallSpeed;
	private int bonusCounter;
	
	//Fredriks variabler:
	private double[] savedSpeeds;
	private int myIterator;
	private final int SAVEDLOOPS = 5;
	private double lastX;
	
	
		
	public GController(double x, double y, Color color, double sizeX_, double sizeY_){
		super(x, y, color, sizeX_, sizeY_);
		p.x = (int) x; p.y =(int) y;
		
		savedSpeeds = new double[SAVEDLOOPS];
		myIterator = 0;
		increaseBallSpeed = false;
		decreaseBallSpeed = false;
		
	}
	
	
	
	//override
	public void move() {
		ballSpeedIncreasementConditions();
		moveController();
		tryConstrain();
		speedCalc();
		return;
	}
	
	/**
	 * Add last speed value to saved speed array.
	 */
	private void speedCalc(){
		savedSpeeds[myIterator++] = x - lastX;
		lastX = x;
		//if(savedSpeeds[myIterator-1] != 0.0)
			//System.out.println("Speed:" + savedSpeeds[myIterator-1]);
		if(myIterator == savedSpeeds.length) myIterator = 0;
	}
	
	/**
	 * For Controller surface collusion handling.
	 * @return Controller surface rectangle
	 */
	public Rectangle getUpperSurfaceRectangle(){
		return new Rectangle((int)this.x, (int)this.y,(int)this.getSizeX() , (int)surfaceHight);
	}
	
	
	/**
	 * Get the value of controllers current speed
	 * @return double
	 */
	public double getCurrentSpeed(){
		double sumOfSavedSpeeds=0;
		for(int i = 0; i < savedSpeeds.length -1; i++){
			sumOfSavedSpeeds += savedSpeeds[i];
		}
		return sumOfSavedSpeeds/(double) SAVEDLOOPS;
	}
	
	/**
	 * Try to set position with mouse.
	 * @param Point
	 */
	public void setControllerPossitionWithMouse(Point p_){
		this.p.x = (int) (p_.x);
		tryConstrain();	
	}
	
	/**
	 * Sets Boolean movement variable true 
	 * @param Keyevent
	 */
	public void keyControllMove(KeyEvent ke){
		int code = ke.getKeyCode();
		switch(code) {
			case KeyEvent.VK_LEFT:	{	moveLeft = true; }; break;
			case KeyEvent.VK_RIGHT:	{	moveRight = true; }; break;
			case KeyEvent.VK_UP:	; break;
			case KeyEvent.VK_DOWN:	; break;
			default: break;
		}
	}
	
	/**
	 * Sets Boolean movement variable false  
	 * @param Keyevent
	 */
	public void keyControllStop(KeyEvent ke){
		int code = ke.getKeyCode();
		switch(code) {
			case KeyEvent.VK_LEFT:	{ moveLeft = false; }; break;
			case KeyEvent.VK_RIGHT:	{ moveRight = false; }; break;
			case KeyEvent.VK_UP:	; break;
			case KeyEvent.VK_DOWN:	; break;
			default: break;
		}
	}
	
	
	/**
	 * Shrink controller 1 step
	 * The movement step is initialized in consturctor
	 */
	public void shrinkController(){
		if(size>-3){
			size--;
			this.sizeX-=oneStepMovement;
			this.x -=oneStepMovement/2; 
		}
		tryConstrain();
	}
	
	/**
	 * Entlargen controller 1 step
	 * The movement step is initialized in consturctor
	 */
	public void entlargenController(){	
		if(size<3){
			size++;
			this.sizeX+=oneStepMovement;
			//this.x +=oneStepMovement/2; 
		}
		tryConstrain();
	}
	
	/**
	 * If movement booleans are true move in that direction.
	 * The movement step is initialized in consturctor
	 * moveLeft / moveRight 
	 */
	public void moveController(){
		if(moveLeft){
			p.x = (int) (tmpX - oneStepMovement);
		}
		if(moveRight){
			p.x = (int) (tmpX + oneStepMovement);
		}
	}
	
	/**
	 * Tests if booleans for ball speed affections are true
	 * if so, counter++. 
	 */
	public void ballSpeedIncreasementConditions(){
		if(increaseBallSpeed()||decreaseBallSpeed()){
			bonusCounter++;
			if(bonusCounter > 200 ){
				increaseBallSpeed=false;
				decreaseBallSpeed=false;
			}
		}
	}
	
	/**
	 * Set increaseBall boolean true
	 * and set decreaseBall false
	 */
	public void runIncreaseBall(){
		bonusCounter=0;
		decreaseBallSpeed=false;
		increaseBallSpeed=true;
	}
	/**
	 *Set decreaseBall boolean true 
	 *and set increaseBAll false
	 */
	public void runDecreaseBall(){
		bonusCounter=0;
		increaseBallSpeed=false;
		decreaseBallSpeed=true;
	}
	
	/**
	 * @return boolean, increase ball speed true / false
	 */
	public Boolean increaseBallSpeed(){
		return increaseBallSpeed;
	}
	
	/**
	 * @return boolean, decrease ball speed true / false
	 */
	public boolean decreaseBallSpeed() {
		return decreaseBallSpeed;	
	}
	
	/**
	 * Any mouse button pressed
	 * Not used
	 */
	public void mouseButtonAction(){
//		ElementHandler.toggleOnOff();
//		System.out.println("Mouse button 1 pressed");
	}
	
	/**
	 * Controller wall collision detection test
	 * If outside keep inside by setting correct values so it 
	 * tuches teh wall and no balls can pass
	 */
	protected void tryConstrain(){
	
		//left and right corner of controller
		double xLeft = p.x - sizeX/2, xRight = p.x+sizeX/2; 
		double x0 = boundBox.x;
		double x1 = x0 + boundBox.width;
		
		
		if( xLeft >= x0 && xRight <= x1) 	{x = xLeft; tmpX=p.x;}
		if( xLeft < x0 ) 					{x = x0;}
		if(	xRight > x1) 					{x = x1-sizeX; p.x = (int) (x+sizeX/2);}
	} 
	
	
	protected void constrain() {
	}

}
